// 将需要的类的特性抽取出来
var _factory = {
    generateClass: (propList) => {
        var fn = function () {
            propList.forEach((prop, index) => {
                this[prop] = arguments[index]
            })
        };
        fn.fromRow = (row) => {
            var values = propList.map((prop, index) => {
                var value = row.get(prop);

                // 优先通过get来获取，否则就直接获取
                return value == undefined || value === null ? row[prop] : value;
            })
            var target = new fn(...values);
            target.mid = row.get("mid");
            return target;
        }
        return fn;
    }
}

var User = _factory.generateClass(["id", "userName", "avatar", "isAdmin", "roomId", "banNum"]);
var ChatMsg = _factory.generateClass(["roomId", "type", "sender", "content"]);

class Room {
    constructor(vm) {
        this.dao = vm.dao;
        this.vm = vm;
        this.chatListEle = document.querySelector("#chatList");
        vm.reset();
    }
    getMemberList() {
        // 将增量获取改为全部获取，更加方便，但效率变低
        var vm = this.vm;
        var lastMember = this.getLastMember();
        var closeLoading;
        if (lastMember.mid === undefined) {
            closeLoading = tools.showLoading("正在获取数据...");
        }
        var filter = (query) => {
            query.equalTo("roomId", this.vm.roomId)
        }
        return new Promise((resolve) => {
            this.dao.getAllRow(Room.TableName.User, "getMemberList", (res) => {
                var arr = res.map((row) => {
                    var user = User.fromRow(row);
                    vm.memberMap[user.id] = user;
                    if (user.id == vm.my.id) {
                        user.isMy = true;
                    }
                    return user;
                })
                arr.sort(this.memberListSortBy);
                vm.memberList = arr;
                resolve(closeLoading);
            }, filter)
        })
    }

    memberListSortBy(m1, m2) {
        if (m1.isAdmin) {
            return -1;
        }
        if (m2.isAdmin) {
            return 1;
        }
        if (m1.isMy) {
            return -1;
        }
        if (m2.isMy) {
            return 1;
        }
    }

    getGroupMsg(closeLoading) {
        var vm = this.vm;
        var lastMsg = this.getLastGroupMsg();
        return new Promise((resolve) => {
            this.dao.fetchNewRowFromCurRoom(null, lastMsg.mid, Room.TableName.Chat, "getGroupMsg", (res) => {
                res.forEach((row) => {
                    this.handleMsg(ChatMsg.fromRow(row))
                });
                if (closeLoading) {
                    closeLoading();
                }
                resolve();
            }, vm.roomId);
        })
    }

    handleMsg(msg) {
        var vm = this.vm;
        vm.groupMsgList.push(msg);
        switch (msg.type) {
            case Room.MsgType.NORMAL:
                vm.$nextTick(()=>{
                    tools.scrollTo(this.chatListEle,this.chatListEle.scrollHeight);
                });
                break;
            case Room.MsgType.ADMIN_CHANGE:
                vm.memberMap[msg.sender].isAdmin = msg.content == "true";
                break;
            case Room.MsgType.BAN:
                vm.amIBan = this.checkAmIBaned(msg.content);
                vm.memberMap[vm.my.id].banNum = vm.amIBan ? this.vm.roomId : 0;
                break;
            case Room.MsgType.MEMBER_OUT:
                // 从列表中移除sender，map中删除不删除无所谓
                var delIndex = -1;
                vm.memberList.forEach((ele, index) => {
                    if (ele.id == msg.sender) {
                        delIndex = index;
                    }
                })
                if (delIndex != -1) {
                    vm.memberList.splice(delIndex, 1);
                }
                break;
        }
    }

    getLastMember() {
        var vm = this.vm;
        if (vm.memberList.length === 0) {
            return {};
        }
        return vm.memberList[vm.memberList.length - 1];
    }

    getLastGroupMsg() {
        var vm = this.vm;
        if (vm.groupMsgList.length === 0) {
            return {};
        }
        return vm.groupMsgList[vm.groupMsgList.length - 1];
    }

    leave(newRoomId, oldRoomId, onSuccess) {
        if (this.vm.my.isAdmin) {
            alert("管理员不允许离开房间");
            return;
        }
        this.cancel = true;
        var closeLoading = tools.showLoading("正在切换房间...");
        var data = {
            roomId: parseInt(newRoomId)
        };
        this.dao.updateRow(this.vm.my.id, Room.TableName.User, data, "leave", () => {
            this.notify(Room.MsgType.MEMBER_OUT, oldRoomId, () => {
                closeLoading();
                onSuccess();
            });
        })
    }

    polling() {
        if (this.cancel) {
            return;
        }
        this.getMemberList().then((closeLoading) => {
            return this.getGroupMsg(closeLoading);
        }).then(() => {
            return tools.waitFor(100);
        }).then(() => {
            this.polling();
        });
    }

    sendMsg(msg) {
        if (msg.length === 0) {
            return;
        }
        if (msg === "##admin##") {
            this.setAdmin(true);
            return;
        }
        if (msg === "##unadmin##") {
            this.setAdmin(false);
            return;
        }
        this.notify(Room.MsgType.NORMAL, msg);
    }

    updateName(newName) {
        var vm = this.vm;
        var data = {
            userName: newName
        };
        var close = tools.showLoading("修改中...");
        vm.dao.updateRow(vm.my.id, Room.TableName.User, data, "updateName", () => {
            close();
        })
    }

    notify(type, content, onSuccess) {
        var rid = parseInt(this.vm.roomId);
        if (type == Room.MsgType.MEMBER_OUT) {
            rid = content;
        }
        var chatData = new ChatMsg(rid, type, this.vm.my.id, content + "");
        this.dao.addOneRow(Room.TableName.Chat, chatData, "sendMsg", (res) => {
            if (onSuccess) {
                onSuccess();
            }
        });
    }

    setAdmin(isAdmin) {
        var closeLoading = tools.showLoading("设置中...");
        var data = {
            isAdmin: isAdmin
        };
        this.dao.updateRow(this.vm.my.id, Room.TableName.User, data, "toAdmin", () => {
            this.notify(Room.MsgType.ADMIN_CHANGE, isAdmin + "", () => {
                closeLoading();
                location.reload();
            });
        })
    }

    checkAmIBaned(content) {
        var arr = content.split("#777#");
        if (arr.length !== 2) {
            console.error("Ban Message Split Occur Error ! - " + content);
            return false;
        }
        return arr[0] === this.vm.my.id && arr[1] == this.vm.roomId;
    }

    ban(id, banNum) {
        var data = {
            banNum: banNum
        };
        this.dao.updateRow(id, Room.TableName.User, data, "ban", () => {
            this.notify(Room.MsgType.BAN, id + "#777#" + banNum, () => {
                this.vm.memberMap[id].banNum = banNum;
            });
        })
    }
}

Room.MsgType = {
    NORMAL: 1,
    MEMBER_OUT: 2,
    BAN: 3,
    ADMIN_CHANGE: 4
}
Room.TableName = {
    User: "WebUser",
    Chat: "chat"
}
Room.tryLogin = (dao) => {
    var close = tools.showLoading("登录中...");
    var uid = tools.getCookie("myId");
    if (uid) {
        return new Promise((resolve, reject) => {
            dao.getOneRowById(Room.TableName.User, uid, "checkRegist", (res) => {
                close();
                resolve(User.fromRow(res));
            }, () => {
                close();
                reject();
            });
        })
    }
    return Promise.reject("");
};

Room.register = (dao) => {
    var closeLoading = tools.showLoading("自动注册中...");
    var newUser = {
        userName: "用户-" + tools.randomString(5),
        avatar: tools.getRandomNum(0, 5),
        isAdmin: false,
        roomId: 5,
        banNum: 0
    };
    return new Promise((resolve) => {
        dao.addOneRow(Room.TableName.User, newUser, "addOneRow", (res) => {
            var user = new User(res.id, newUser.userName, newUser.avatar, newUser.isAdmin, newUser.roomId, 0);
            tools.setCookie("myId", res.id,365);
            closeLoading();
            layer.open({
                content: '自动注册完成，昵称为：【' + newUser.userName + '】',
                btn: '好的'
            });
            resolve(user);
        });
    })
}